package main

import (
	"crypto/tls"
	"fmt"
	"net/url"
	"strconv"
	"syscall"
	"time"

	gosocketio "gitee.com/flhk1314/go-socket.io"
	"gitee.com/flhk1314/go-socket.io/transport"
)

type ClientIo struct {
	id     string
	ip     string
	port   int
	query  string
	enable bool
	client *gosocketio.Client
}

func main() {
	setRlimit()
	MediaSort()
	// local()
	// remote_live()
}
func NewClientIo(id string, ip string, port int, query string, cb func(event string, callbackPtr *ClientIo), mode string) (*ClientIo, error) {
	clientIo := new(ClientIo)
	clientIo.id = id
	clientIo.ip = ip
	clientIo.port = port
	clientIo.query = query
	clientIo.enable = false

	tr := transport.DefaultWebsocketTransport()
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	for {
		var websocketURL string
		if mode == "local" {
			websocketURL = fmt.Sprintf("ws://%s:%d/socket.io/?transport=websocket&%s", clientIo.ip, port, clientIo.query)
		} else {
			websocketURL = fmt.Sprintf("wss://%s:%d/socket.io/?transport=websocket&%s", clientIo.ip, port, clientIo.query)
		}
		fmt.Printf("ClientIo url is %s\n", websocketURL)
		client, err := gosocketio.Dial(websocketURL, tr)
		fmt.Println("socket 连接成功")
		if err != nil {
			fmt.Printf("ClientIo connect to %s:%d failed[%s]\n", ip, port, err.Error())
			time.Sleep(100 * time.Millisecond)
			continue
		}
		err = client.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
			clientIo.enable = true
			cb(gosocketio.OnConnection, clientIo)
		})
		if err != nil {
			fmt.Printf("ClientIo regist connection callback function to %s:%d failed[%s]\n", ip, port, err.Error())
			return clientIo, err
		}
		err = client.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
			clientIo.enable = false
			cb(gosocketio.OnDisconnection, clientIo)
		})
		if err != nil {
			fmt.Printf("ClientIo regist disconnection callback function to %s:%d failed[%s]\n", ip, port, err.Error())
			return clientIo, err
		}
		err = client.On("pushUpdateSpectatorStatus", func(c *gosocketio.Channel) {
			fmt.Println("ClientIo receive pushUpdateSpectatorStatus event")
		})
		if err != nil {
			fmt.Printf("ClientIo regist pushUpdateSpectatorStatus callback function to %s:%d failed[%s]\n", ip, port, err.Error())
			return clientIo, err
		}
		clientIo.client = client
		break
	}
	return clientIo, nil
}

func MediaSort() {
	// {"EIO":["4"],"displayName":["李建宏"],"gmtype":["gmtype"],"lg":["gky"],"mode":["mcalling"],"peerName":["4611686027042922256"],
	// "platform":["pc-win"],"roomId":["4611686027042922256-1742815890246"],"rtcType":["unbindconfer"],"rtcsdk":["230227-1003"],
	// "t":["1742815903"],"transport":["websocket"],"verapp":["6.1.120.4"],"version":["3.3.7"]}
	port := 10670
	serverip := "192.168.137.25"
	logo := "bxy"
	roomId := "21256856927_1742874750004"
	peerName := "21256856927"
	mode := "mcalling"
	fmt.Println("StartServer..........................")
	query := url.Values{}
	query.Set("EIO", "4")
	query.Set("displayName", "卜锦元")
	query.Set("gmtype", "gmtype")
	query.Set("mode", mode)
	query.Set("roomId", roomId)
	query.Set("lg", logo)
	query.Set("peerName", peerName)
	query.Set("platform", "pc-win")
	query.Set("rtcType", "unbindconfer")
	query.Set("rtcsdk", "230227-1003")
	query.Set("t", "1742874757")
	query.Set("transport", "websocket")
	query.Set("verapp", "6.1.120.4")
	query.Set("version", "3.3.7")
	queryStr := query.Encode()
	Clientio, err := NewClientIo(fmt.Sprintf("%d", 88888), serverip, port, queryStr, cback, mode)
	if err != nil {
		fmt.Printf("newClient err:%s\n", err)
		return
	}
	data := map[string]interface{}{
		"data": map[string]interface{}{
			"addr": serverip,
			"port": 10678,
		},
	}
	time.Sleep(3 * time.Second)
	Clientio.Send("broadcast", data)
	select {}
}

func local() {
	serverip := "192.168.137.25"
	port := 8000
	logo := "bxynj"
	roomId := "4611686027042932044-1721697151754"
	conferId := "192964253"
	peerName := "21270000000"
	mode := "local"

	fmt.Println("StartServer..........................")
	query := url.Values{}
	query.Set("roomId", roomId)
	query.Set("conferId", conferId)
	query.Set("lg", logo)

	tempPeerName, err := strconv.Atoi(peerName)
	if err != nil {
		fmt.Printf("newClient err:%s\n", err)
		return
	}
	for i := 0; i < 1000; i++ {

		tempPeerName += 1
		query.Set("peerName", strconv.Itoa(tempPeerName))
		queryStr := query.Encode()
		Clientio, err := NewClientIo(fmt.Sprintf("%d", i), serverip, port, queryStr, cback, mode)
		if err != nil {
			fmt.Printf("newClient err:%s\n", err)
			return
		}
		data := map[string]interface{}{
			"method": "connectLiveBroadcast",
			"params": map[string]interface{}{
				"addr":       serverip,
				"conferId":   conferId,
				"elogo":      logo,
				"extendJson": "",
				"organizeId": "4843162373457432",
				"peerName":   strconv.Itoa(tempPeerName),
				"platform":   "pc",
				"spy":        "true",
				"userName":   "",
				"verapp":     "6.0.4.0",
				"version":    1,
			},
		}
		Clientio.Send("conference", data)
		time.Sleep(10 * time.Millisecond)
		fmt.Printf("人员数量 %d\n", i)
	}
}

func remote_live() {
	port := 10770
	serverip := "192.168.140.237"
	logo := "bxy"
	roomId := "21256856834-1721731562654"
	conferId := "262547153"
	peerName := "21290000000"
	mode := "144288470"

	fmt.Println("StartServer..........................")
	query := url.Values{}
	query.Set("roomId", roomId)
	query.Set("conferId", conferId)
	query.Set("lg", logo)

	tempPeerName, err := strconv.Atoi(peerName)
	if err != nil {
		fmt.Printf("newClient err:%s\n", err)
		return
	}

	for i := 0; i < 10000; i++ {
		tempPeerName += 1
		query.Set("peerName", strconv.Itoa(tempPeerName))
		queryStr := query.Encode()
		Clientio, err := NewClientIo(fmt.Sprintf("%d", i), serverip, port, queryStr, cback, mode)
		if err != nil {
			fmt.Printf("newClient err:%s\n", err)
			return
		}
		data := map[string]interface{}{
			"method": "connectLiveBroadcast",
			"params": map[string]interface{}{
				"addr":       serverip,
				"conferId":   conferId,
				"elogo":      logo,
				"extendJson": "",
				"organizeId": "4843162373457432",
				"peerName":   strconv.Itoa(tempPeerName),
				"platform":   "pc",
				"spy":        "true",
				"userName":   "",
				"verapp":     "6.0.4.0",
				"version":    1,
			},
		}
		Clientio.Send("conference", data)
		time.Sleep(10 * time.Millisecond)
		fmt.Printf("人员数量 %d\n", i)
	}
}
func setRlimit() {
	var rlimit syscall.Rlimit
	err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit)
	if err != nil {
		fmt.Println("Error getting rlimit:", err)
		return
	}

	fmt.Println("Current rlimit:", rlimit)
	newRlimit := syscall.Rlimit{
		Cur: 10000,
		Max: 10000,
	}

	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &newRlimit)
	if err != nil {
		fmt.Println("Error setting rlimit:", err)
		return
	}

	fmt.Println("New rlimit:", newRlimit)
}

func (clientIo *ClientIo) Send(event string, data map[string]interface{}) {
	if !clientIo.enable {
		fmt.Println("ClientIo is not enable")
		return
	}
	fmt.Printf("ClientIo send event %s, data %v\n", event, data)
	clientIo.client.Emit(event, data)
}

func (clientIo *ClientIo) Ack(event string, payload map[string]interface{}, cb func(response string, err error)) {
	if false == clientIo.enable {
		return
	}
	go func(event string, payload map[string]interface{}, cb func(response string, err error)) {
		response, err := clientIo.client.Ack(event, payload, 30*time.Second)
		if err != nil {
			cb("", err)
		} else {
			cb(response, nil)
		}
	}(event, payload, cb)
}

func (clientIo *ClientIo) Close() {
	clientIo.client.Close()
}

func cback(event string, MClient *ClientIo) {
	switch event {
	case gosocketio.OnConnection:
		fmt.Printf("MClient connect server success==%s:%d\n", MClient.ip, MClient.port)
		break
	case gosocketio.OnDisconnection:
		fmt.Printf("MClient disconnect to server ==%s:%d!\n", MClient.ip, MClient.port)
		MClient.enable = false
		break
	}
}
